import 'dart:async';
import 'dart:math';
import 'package:audioplayers/audioplayers.dart';
import 'package:flip_card/flip_card.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/widgets.dart';
import 'dart:math' as Math;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '拯救国王',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(fontFamily: 'kangkang'),
      home: MyHomePage(title: ''),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final data = [
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
  ];

  final genGame = ["right", "left", "up", "down"];

  AudioPlayer player = AudioPlayer();

  List<int> genedGame = [];
  List<int> positionGreen = [];
  int nowPositon = 12;
  int index = 0;

  String template = "";

  bool gameStart = false;
  bool onCheckPress = true;
  bool checkGameOver = false;

  double characterPositionX = 0;
  double characterPositionY = 0;
  int step = 0;

  int level = 1;

  final _stickyKey = GlobalKey();
  late final RenderBox sizeGrid;
  double staticMoveX = 0.0;
  double staticMoveY = 0.0;

  var cardKeys = Map<int, GlobalKey<FlipCardState>>();
  GlobalKey<FlipCardState>? lastFlipped;

  int x = 0;
  int y = 0;

  void startGame() {
    setState(() {
      gameStart = true;
      genedGame = [];
      positionGreen = [];
      index = 0;
      step = 0;
      level += 1;
      checkGameOver = false;
    });
    generateGame();
  }

  void checkOutOfCard() {
    int random = Random().nextInt(genGame.length);
    switch (random) {
      case 0:
        setState(() {
          x += 1;
          nowPositon += 1;
          positionGreen.add(nowPositon);
        });
        if (x > 2) {
          setState(() {
            random = 1;
            x -= 2;
            positionGreen.removeLast();
            nowPositon -= 2;
            positionGreen.add(nowPositon);
          });
        }
        break;
      case 1:
        setState(() {
          x -= 1;
          nowPositon -= 1;
          positionGreen.add(nowPositon);
        });
        if (x < -2) {
          setState(() {
            random = 0;
            x += 2;
            positionGreen.removeLast();
            nowPositon += 2;
            positionGreen.add(nowPositon);
          });
        }
        break;
      case 2:
        setState(() {
          y -= 1;
          nowPositon -= 5;
          positionGreen.add(nowPositon);
        });
        if (y < -2) {
          setState(() {
            random = 3;
            y += 2;
            positionGreen.removeLast();
            nowPositon += 10;
            positionGreen.add(nowPositon);
          });
        }
        break;
      case 3:
        setState(() {
          y += 1;
          nowPositon += 5;
          positionGreen.add(nowPositon);
        });
        if (y > 2) {
          setState(() {
            random = 2;
            y -= 2;
            positionGreen.removeLast();
            nowPositon -= 10;
            positionGreen.add(nowPositon);
          });
        }
        break;
    }
    print("x = $x");
    print("y = $y");
    genedGame.add(random);
    return;
  }

  void generateGame() async {
    for (var i = 0; i < level; i++) {
      checkOutOfCard();
    }

    for (var i = 0; i < genedGame.length; i++) {
      await Future.delayed(Duration(seconds: 1));
      setState(() {
        template = genGame[genedGame[index]].toString();
        index += 1;
      });
      await Future.delayed(Duration(seconds: 2));
      setState(() {
        template = "";
      });
      if (index == genedGame.length) {
        template = "GOGOGO";
        startMove();
      }
    }
  }

  void startMove() {
    setState(() {
      onCheckPress = false;
    });
  }

  void playerMovement(detail) {
    int sensitivity = 6;
    if (onCheckPress == true) {
      return;
    }

    if (detail.delta.dx > sensitivity &&
        characterPositionX < (staticMoveX * 2)) {
      setState(() {
        characterPositionX += staticMoveX;
        onCheckPress = true;
        checkBomb("right");
      });
    } else if (detail.delta.dx < -sensitivity &&
        characterPositionX > -(staticMoveX * 2)) {
      setState(() {
        characterPositionX -= staticMoveX;
        onCheckPress = true;
        checkBomb("left");
      });
    } else if (detail.delta.dy > sensitivity &&
        characterPositionY < (staticMoveY * 2)) {
      print("down");
      setState(() {
        characterPositionY += staticMoveY;
        onCheckPress = true;
        checkBomb("down");
      });
    } else if (detail.delta.dy < -sensitivity &&
        characterPositionY > -(staticMoveY * 2)) {
      print("up");
      setState(() {
        characterPositionY -= staticMoveY;
        onCheckPress = true;
        checkBomb("up");
      });
    }
  }

  void checkBomb(move) async {
    flipCard();
    await Future.delayed(Duration(seconds: 2));
    print(move);
    print(genGame[genedGame[step]]);
    if (move == genGame[genedGame[step]]) {
      setState(() {
        template = "nice";
      });
      await Future.delayed(Duration(milliseconds: 500));
      setState(() {
        template = "";
        step += 1;
      });
      if (step == genedGame.length) {
        setState(() {
          template = "letgo";
        });
        player.play('assets/sound/point.wav');
        startGame();
        return;
      }
      startMove();
    } else {
      gameOver();
    }
  }

  void flipCard() async {
    await Future.delayed(Duration(seconds: 1));
    player.play('assets/sound/flipcard.mp3');
    for (int i = 0; i < data.length; i++) {
      cardKeys[i]?.currentState?.toggleCard();
    }
    await Future.delayed(Duration(seconds: 1));
    if (checkGameOver == false) {
      player.play('assets/sound/flipcard.mp3');
    }
    for (int i = 0; i < data.length; i++) {
      cardKeys[i]?.currentState?.toggleCard();
    }
    return;
  }

  void gameOver() {
    player.play('assets/sound/gameover.wav');
    setState(() {
      gameStart = false;
      genedGame = [];
      index = 0;
      template = "";
      onCheckPress = true;
      characterPositionX = 0;
      characterPositionY = 0;
      step = 0;
      x = 0;
      y = 0;
      level = 1;
      nowPositon = 12;
      positionGreen = [];
      checkGameOver = true;
    });
  }

  @override
  void initState() {
    WidgetsBinding.instance!.addPostFrameCallback(_afterLayout);
    super.initState();
  }

  _afterLayout(_) {
    setState(() {
      sizeGrid = _stickyKey.currentContext!.findRenderObject() as RenderBox;
      staticMoveX = sizeGrid.size.width == 400
          ? sizeGrid.size.width * 0.2
          : sizeGrid.size.width * 0.199;
      staticMoveY = sizeGrid.size.width == 400
          ? sizeGrid.size.width * 0.2
          : sizeGrid.size.width * 0.199;
    });
  }

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return Scaffold(
      backgroundColor: Color(0xFFFFD6B1),
      body: SafeArea(
        bottom: false,
        child: GestureDetector(
          onPanUpdate: (detail) {
            playerMovement(detail);
          },
          child: Stack(
            children: [
              arrowQuiz(size),
              Padding(
                padding: const EdgeInsets.all(5.0),
                child: Center(
                  child: Container(
                    width: 400,
                    height: 400,
                    key: _stickyKey,
                    child: Stack(
                      alignment: Alignment.center,
                      children: [
                        cardBoomm(),
                        _stickyKey.currentContext != null
                            ? playerGame()
                            : Text("")
                      ],
                    ),
                  ),
                ),
              ),
              !gameStart ? menuGame(size) : Text(""),
            ],
          ),
        ),
      ),
    );
  }

  Positioned playerGame() {
    return Positioned(
      child: Container(
          transform: Matrix4.translationValues(-(sizeGrid.size.width * 0.05),
              -(sizeGrid.size.height * 0.04), 0.0),
          decoration: BoxDecoration(
              color: Colors.red,
              borderRadius: BorderRadius.all(Radius.circular(3))),
          width: sizeGrid.size.width * 0.1,
          height: sizeGrid.size.width * 0.1,
          child: Text("")),
      left: characterPositionX + (sizeGrid.size.width * 0.5),
      top: characterPositionY + (sizeGrid.size.width * 0.49),
    );
  }

  Positioned arrowQuiz(Size size) {
    double calAnge = template == "right"
        ? Math.pi / 2
        : template == "left"
            ? Math.pi / -2
            : template == "up"
                ? 0
                : template == "down"
                    ? -Math.pi
                    : Math.pi * 1;
    return Positioned(
      child: Container(
          width: size.width,
          child: gameStart
              ? Center(
                  child: template == "up" ||
                          template == "down" ||
                          template == "left" ||
                          template == "right"
                      ? Transform.rotate(
                          angle: calAnge,
                          child: Image.asset(
                            "assets/images/up-arrow.png",
                            width: 90,
                          ),
                        )
                      : template == "nice"
                          ? Image.asset("assets/images/like.png", width: 50)
                          : template == "GOGOGO"
                              ? Container(
                                  width: 350,
                                  height: 200,
                                  decoration: BoxDecoration(
                                    image: DecorationImage(
                                        image: AssetImage(
                                            "assets/images/start-button.png"),
                                        fit: BoxFit.fill),
                                  ),
                                  child: Container(
                                    padding:
                                        EdgeInsets.fromLTRB(60, 60, 70, 60),
                                    child: Text(
                                      '请按照刚刚神秘人的手势方向循序一步步移动红色方块 🟥 ',
                                      style: TextStyle(
                                          fontSize: 16,
                                          fontWeight: FontWeight.bold,
                                          color: Color(0xFF503614)),
                                    ),
                                  ),
                                )
                              : template == "letgo"
                                  ? Image.asset(
                                      "assets/images/crown.png",
                                      width: size.height * 0.1,
                                    )
                                  : Text("$template"))
              : Text("")),
      top: (size.height * 0.05),
    );
  }

  GridView cardBoomm() {
    return GridView.builder(
      physics: NeverScrollableScrollPhysics(),
      itemCount: data.length,
      itemBuilder: (context, indexCard) {
        cardKeys.putIfAbsent(indexCard, () => GlobalKey<FlipCardState>());
        GlobalKey<FlipCardState>? thisCard = cardKeys[indexCard];
        return FlipCard(
          flipOnTouch: false,
          direction: FlipDirection.HORIZONTAL,
          key: thisCard,
          front: Container(
            decoration: BoxDecoration(
                color: Colors.white,
                border: Border.all(
                  color: Color(0xFF503614),
                  width: 5,
                ),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withOpacity(0.2),
                    spreadRadius: 1,
                    blurRadius: 1,
                    offset: Offset(0, 0), // changes position of shadow
                  ),
                ],
                borderRadius: BorderRadius.all(Radius.circular(13))),
            child: Center(
              child: Image.asset(
                "assets/images/question-mark.png",
                color: Color(0xFF503614),
                width: 40,
              ),
            ),
          ),
          back: positionGreen.length > 0
              ? Container(
                  decoration: BoxDecoration(
                      color: Colors.white,
                      border: Border.all(
                        color: positionGreen[step] == indexCard
                            ? Colors.yellow
                            : Colors.red,
                        width: 5,
                      ),
                      boxShadow: [
                        BoxShadow(
                          color: Colors.black.withOpacity(0.2),
                          spreadRadius: 1,
                          blurRadius: 1,
                          offset: Offset(0, 0),
                        ),
                      ],
                      borderRadius: BorderRadius.all(Radius.circular(13))),
                  child: Center(
                    child: Image.asset(
                      positionGreen[step] == indexCard
                          ? "assets/images/c.png"
                          : "assets/images/round-bomb.png",
                      color: positionGreen[step] == indexCard
                          ? Colors.yellow
                          : Colors.red,
                      width: 40,
                    ),
                  ),
                )
              : Text(''),
        );
      },
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 5, crossAxisSpacing: 5, mainAxisSpacing: 5),
    );
  }

  Container menuGame(Size size) {
    return Container(
        width: size.width,
        height: size.height,
        decoration: BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
            colors: [
              Color(0xFFFFD6B1),
              Color(0xFFA76E3D),
            ],
          ),
        ),
        child: ListView(
          children: [
            Container(
              height: size.height * 0.1,
            ),
            checkGameOver
                ? Container(
                    height: size.height * 0.4,
                    child: Image.asset(
                      'assets/images/fail.png',
                    ),
                  )
                : Container(
                    height: size.height * 0.4,
                    child: Image.asset(
                      'assets/images/king.png',
                    ),
                  ),
            Container(height: 20),
            Center(
              child: Container(
                width: size.width * 0.8,
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    checkGameOver
                        ? Text(
                            "国王被捕了",
                            textAlign: TextAlign.left,
                            style: TextStyle(
                                color: Color(0xFFC72D2D), fontSize: 30),
                          )
                        : Text(
                            "解救国王",
                            textAlign: TextAlign.left,
                            style: TextStyle(
                              color: Colors.white,
                              fontSize: 35,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                    SizedBox(height: 20),
                    Text(
                      "国王深陷战场无法逃脱，根据神秘人的指引方向一步步带领国王找到藏身草丛，逃出重围！",
                      textAlign: TextAlign.left,
                      style: TextStyle(color: Colors.white, fontSize: 20),
                    ),
                  ],
                ),
              ),
            ),
            Container(
              height: size.height * 0.05,
            ),
            Center(
                child: GestureDetector(
              onTap: () {
                startGame();
              },
              child: Container(
                  width: size.width * 0.8,
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.all(Radius.circular(4)),
                    color: Colors.white,
                    boxShadow: [
                      BoxShadow(
                        color: Colors.black.withOpacity(0.2),
                        spreadRadius: 3,
                        blurRadius: 10,
                        offset: Offset(0, 5),
                      ),
                    ],
                  ),
                  child: Padding(
                    padding: const EdgeInsets.all(15.0),
                    child: Text(
                      checkGameOver ? "再次尝试" : "开始",
                      textAlign: TextAlign.center,
                      style: TextStyle(
                        color: Color(0xFFA76E3D),
                        fontSize: 25,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  )),
            )),
          ],
        ));
  }
}
